﻿using System;
using CzfUDP;
using System.Threading;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using CzfSDK;
using System.Net.Sockets;
using System.Net;

namespace Test
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			int port = 11122;
//			  string host = "120.24.186.67";
			string host = "127.0.0.1";

			Console.WriteLine ("input host:");
			var sss = Console.ReadLine ();
			if (sss != "")
				host = sss;

			Console.WriteLine ("1-StartServer");
			Console.WriteLine ("21-StartClient with Unreliable");
			Console.WriteLine ("22-StartClient with UnreliableSequenced");
			Console.WriteLine ("23-StartClient with ReliableUnordered");
			Console.WriteLine ("24-StartClient with ReliableOrdered");
			Console.WriteLine ("3-StartServer without output");
			Console.WriteLine ("4-StartTcpServer");
			Console.WriteLine ("5-StartTcpServer without output");
			Console.WriteLine ("6-StartTcpClient");
			Console.WriteLine ("7-StartFrameRateUDPServer");

			var s = Console.ReadLine ();
			if (s == "1")
				StartServer (port);
			else if(s == "21")
				StartClient (host, port, NetDeliveryMethod.Unreliable);
			else if(s == "22")
				StartClient (host, port, NetDeliveryMethod.UnreliableSequenced);
			else if(s == "23")
				StartClient (host, port, NetDeliveryMethod.ReliableUnordered);
			else if(s == "24")
				StartClient (host, port, NetDeliveryMethod.ReliableOrdered);
			else if(s == "3")
				StartServer (port, false);
			else if(s == "4")
				StartTcpServer (port + 1);
			else if(s == "5")
				StartTcpServer (port + 1, false);
			else if(s == "6")
				StartTcpClient (host, port + 1);
			else if(s == "7")
				StartFrameRateUDPServer (port);
		}

		static object lock1 = new object ();

		static void Task1()
		{
			Console.WriteLine ("task1---1");
			lock (lock1) {
				Console.WriteLine ("task1---2");
			}
			Console.WriteLine ("task1---3");
		}

		static void ShowRecive(CzfNetClient client, byte[] bytes)
		{
			var str = UnicodeEncoding.UTF8.GetString(bytes);
			Console.WriteLine("recive threadId("+ Thread.CurrentThread.ManagedThreadId +"):" + str);
		}

		static void ShowRecive(CzfUDPClient client, byte[] bytes)
		{
			var str = UnicodeEncoding.UTF8.GetString(bytes);
			Console.WriteLine("recive threadId("+ Thread.CurrentThread.ManagedThreadId +"):" + str);
		}

		static void StartTcpClient(string host, int port)
		{
			var sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			var ipe = new IPEndPoint (IPAddress.Parse(host), port);
			sock.Connect (ipe);
			var client = new CzfTcpClient (sock);

			client.OnClose += (obj) => {
				Console.WriteLine("连接关闭!!!");
			};
			client.OnRecive += ShowRecive;
			client.BeginRecive ();
			client.Send (UnicodeEncoding.UTF8.GetBytes("立刻发送数据包!!"));

			Console.WriteLine ("start client:");
			while (true) {
				var s = Console.ReadLine ();
				if (s == "test") {
					// 测试丢包率和延迟
					Console.WriteLine ("准备测试丢包率和延迟");
					Console.WriteLine ("每秒多少个包:");
					int per = Convert.ToInt32 (Console.ReadLine());
					Console.WriteLine ("测试多少秒:");
					int time = Convert.ToInt32 (Console.ReadLine());
					Console.WriteLine ("每个包的大小:");
					byteCount = Convert.ToInt32 (Console.ReadLine());

					Console.WriteLine ("开始测试!!!");
					start = DateTime.Now;
					totalMax = per * time;
					client.OnRecive -= ShowRecive;
					client.OnRecive -= TotalRecive;
					client.OnRecive += TotalRecive;
					total = 0;
					bytes = new byte[byteCount];
					for (int i = 0; i < byteCount; i++) {
						bytes [i] = (byte)(i % 255);
					}
					int t = 0;
					while (t < time) {
						int c = 0;
						while (c < per) {
//							Task.Run (()=>{
							client.Send(bytes);
//							});
							c++;
						}
						t++;
						Console.WriteLine ("已发送:" + (t*c));
						Thread.Sleep (1000);
					}
					Console.WriteLine ("发送完成!!!");
				} else if(s == "show"){
				}else 
					client.Send (UnicodeEncoding.UTF8.GetBytes(s));
			}
		}



		static void StartClient(string host, int port, NetDeliveryMethod netDeliveryMethod)
		{
			var listener = new CzfUDP.CzfUdpListener (NewThread, (time) => {
				Task.Delay(time).Wait();
			});
			listener.OnException += (e) => {
				throw e;
			};

			var client = listener.Connect (host, port, netDeliveryMethod);
			if (client == null) {
				Console.WriteLine ("建立连接失败");
				return;
			}
			client.OnConnect += (obj) => {
				Console.WriteLine("连接成功!!!");
			};
			client.OnClose += (obj) => {
				Console.WriteLine("连接关闭!!!");
			};
			client.OnRecive += ShowRecive;

			client.Send (UnicodeEncoding.UTF8.GetBytes("立刻发送数据包!!"));

			Console.WriteLine ("start client:");
			while (true) {
				var s = Console.ReadLine ();
				if (s == "test") {
					// 测试丢包率和延迟
					Console.WriteLine ("准备测试丢包率和延迟");
					Console.WriteLine ("每秒多少个包:");
					int per = Convert.ToInt32 (Console.ReadLine());
					Console.WriteLine ("测试多少秒:");
					int time = Convert.ToInt32 (Console.ReadLine());
					Console.WriteLine ("每个包的大小:");
					byteCount = Convert.ToInt32 (Console.ReadLine());

					Console.WriteLine ("开始测试!!!");
					start = DateTime.Now;
					totalMax = per * time;
					client.OnRecive -= ShowRecive;
					client.OnRecive -= TotalRecive;
					client.OnRecive += TotalRecive;
					total = 0;
					bytes = new byte[byteCount];
					for (int i = 0; i < byteCount; i++) {
						bytes [i] = (byte)(i % 255);
					}
					int t = 0;
					while (t < time) {
						int c = 0;
						while (c < per) {
							Task.Run (()=>{
								client.Send(bytes);
							});
							c++;
						}
						t++;
						Console.WriteLine ("已发送:" + (t*c));
						Thread.Sleep (1000);
					}
					Console.WriteLine ("发送完成!!!");
				} else if(s == "show"){
					client.DebugInfo ();
					Console.WriteLine ("平均网络延迟: " + client.ARTT + "ms");
				}else 
					client.Send (UnicodeEncoding.UTF8.GetBytes(s));
			}
		}

		static byte[] bytes;
		static object total_lock = new object ();
		static int total;
		static int totalMax;
		static int byteCount;
		static DateTime start;
		static void TotalRecive(CzfNetClient client, byte[] bts)
		{
			if (bts.Length != bytes.Length)
				Console.WriteLine ("包长度不对:" + bts.Length +"|" +bytes.Length);
			for (int i = 0; i < bts.Length; i++) {
				if (bts [i] != bytes [i]) {
					Console.WriteLine ("包长内容不对:");
					for (int ii = 0; ii< bts.Length; ii++) {
						Console.Write (" " + bts [ii]);
					}
					Console.WriteLine ();
					break;
				}
			}

			lock (total_lock) {
				total++;
				if (total % 100 == 0)
					Console.WriteLine ("收到:" + total);

				if (total == totalMax) {
					Console.WriteLine ("完成,用时:" + (DateTime.Now - start).TotalSeconds + "秒");
				}
			}
		}

		static void TotalRecive(CzfUDPClient client, byte[] bts)
		{
			if (bts.Length != bytes.Length)
				Console.WriteLine ("包长度不对:" + bts.Length +"|" +bytes.Length);
			for (int i = 0; i < bts.Length; i++) {
				if (bts [i] != bytes [i]) {
					Console.WriteLine ("包长内容不对:");
					for (int ii = 0; ii< bts.Length; ii++) {
						Console.Write (" " + bts [ii]);
					}
					Console.WriteLine ();
					break;
				}
			}

			lock (total_lock) {
				total++;
				if (total % 100 == 0)
					Console.WriteLine ("收到:" + total);

				if (total == totalMax) {
					Console.WriteLine ("完成,用时:" + (DateTime.Now - start).TotalSeconds + "秒");
				}
			}
		}

		static void StartTcpServer(int port, bool outPut = true){
			var listener = new CzfTcpListener (port);
			listener.OnAccept += (l, client) => {
				if(outPut)
					client.OnRecive += ShowRecive;
				client.OnRecive += (arg1, arg2) => {
					client.Send(arg2);
				};
				client.BeginRecive();
			};
			listener.Start ();

			Console.WriteLine ("start server:");
			while (true) {
				Console.ReadLine ();

			}
		}

		static void StartServer(int port, bool outPut = true)
		{
			var listener = new CzfUDP.CzfUdpListener (NewThread, (time) => {
				Task.Delay(time).Wait();
			});
			listener.OnAccept += (client) => {
				if(outPut)
					client.OnRecive += ShowRecive;
				client.OnRecive += (arg1, arg2) => {
					if(arg2.Length == 0)
						Console.WriteLine("arg2.Length == 0");
					client.Send(arg2);
				};
			};

			listener.OnException += (e) => {
				Console.WriteLine(e.ToString());
			};

//			listener.DebugTask ();

			listener.StartListen (port);

			Console.WriteLine ("start server:");
			while (true) {
				var s = Console.ReadLine ();
				var bts = UnicodeEncoding.UTF8.GetBytes (s);
				foreach (var c in CzfUDPClient.allClients.Values) {
					c.Send (bts);
				}
			}
		}

		static void StartFrameRateUDPServer(int port)
		{
			// log
			var logConfigPath = Environment.CurrentDirectory + "/CzfLog/log_config.xml";
			Console.WriteLine ("log_config:"+logConfigPath);
			new CzfLog_Log4Net (logConfigPath);
			CzfLog.Info ("start log ok...");
			AppDomain.CurrentDomain.UnhandledException += (sender, e) => {
				CzfLog.Error("未捕获的异常", (Exception)e.ExceptionObject);
			};


			var proto = new TestProto (0);
			var listener = new CzfSDK.CzfTcpListener (port);
			listener.OnException += (e) => {
				Console.WriteLine(e.ToString());
			};
//			listener.OnAccept += (l, c) => {
//				((CzfUdpClient)c).baseUdp.clientTimeout = 10000;
//			};
			var net = new CzfNetManager (proto, listener);
			net.Start ();
			Console.WriteLine ("start server:");
			while (true) {
				var s = Console.ReadLine ();
				if (s == "start")
					proto.Start ();
			}
		}

		static void NewThread(ThreadStart action)
		{
			var task = new Task (()=>{
				action();
			}, TaskCreationOptions.LongRunning);
			task.Start ();
		}
	}
}
